package top.kaoshanji.ch12;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 代码清单 ch12-05：阻塞队列示例(12.5.1节、搜索文件然后根据关键字搜索打印行号)
 * 并未执行
 * author kaoshanji
 * ^_^
 * create time 2024/11/29 18:49
 */
public class BlockingQueueTest {

    private static final Logger logger = LogManager.getLogger(BlockingQueueTest.class);

    private static final int FILE_QUEUE_SIZE = 10;
    private static final int SEARCH_THREADS = 100;
    private static final Path DUMMY = Path.of("");

    // 阻塞队列，是一个属性
    private static BlockingQueue<Path> queue = new ArrayBlockingQueue<>(FILE_QUEUE_SIZE);

    public static void main(String[] args) {
        logger.info("...代码清单 ch12-05：阻塞队列示例(12.5.1节、搜索文件然后根据关键字搜索打印行号)...");

        try (var in = new Scanner(System.in)) {
            System.out.print("Enter base directory (e.g. /opt/jdk-11-src): ");
            String directory = in.nextLine();
            System.out.print("Enter keyword (e.g. volatile): ");
            String keyword = in.nextLine();

            Runnable enumerator = () -> {
                try {
                    enumerate(Path.of(directory));
                    queue.put(DUMMY);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            };

            new Thread(enumerator).start();

            for (int i = 1; i <= SEARCH_THREADS; i++) {
                Runnable searcher = () -> {
                    try {
                        var done = false;
                        while (!done) {
                            Path file = queue.take();
                            if (file == DUMMY) {
                                queue.put(file);
                                done = true;
                            } else {
                                search(file, keyword);
                            }

                        }

                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                };

                new Thread(searcher).start();

            }

        }


    }

    // 变量目录下的文件，并添加到队列中
    public static void enumerate(Path directory) throws IOException, InterruptedException {

        try (Stream<Path> children = Files.list(directory)) {
            for (Path child: children.collect(Collectors.toList())) {
                if (Files.isDirectory(child)) {
                    enumerate(child);
                } else {
                    queue.put(child);
                }
            }

        }

    }

    // 从队列里取出文件，然后根据关键字搜索并打印行号
    public static void search(Path file, String keyword) throws IOException {

        try (var in = new Scanner(file, StandardCharsets.UTF_8)){
            int lineNumber = 0;
            while (in.hasNext()) {
                lineNumber++;
                String line = in.nextLine();
                if (line.contains(keyword)) {
                    System.out.printf("%s:%d:%s%n", file, lineNumber, line);
                }

            }
        }
    }



}
